﻿using System;
using System.Linq;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using Pharmacy.Data;
using Pharmacy.Entities;
using Pharmacy.Settings.BusinessLayer;
using Pharmacy.Windows.Forms.Properties;
using PrintReportSample;

namespace Pharmacy.Windows.Forms
{
    /// <summary>
    /// </summary>
    public partial class MiniFormPrescription : XtraForm
    {
        private TList<Stock> all;
        private bool autoStock;
        private PrescriptionDetail editItem;
        private TList<PrescriptionDetail> listDetails;
        private CmsPatient patient;

        /// <summary>
        /// 	Form Prescription
        /// </summary>
        public MiniFormPrescription()
        {
            InitializeComponent();
            LoadDefault();
        }

        /// <summary>
        /// </summary>
        public TextBox TbPatientCode
        {
            get { return tb_PatientCode; }
            set { tb_PatientCode = value; }
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Control | Keys.P:
                    btn_Print_Click(null, null);
                    return true;
                case Keys.Control | Keys.D:
                    customGridLookUpEdit1.Focus();
                    return true;
                case Keys.Control | Keys.T:
                    tb_PatientCode.Focus();
                    return true;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        private void LoadDefault()
        {
            all = DataRepository.StockProvider.GetMax("All");
            DataRepository.StockProvider.DeepLoad(all);
            //tb_PatientCode.Text = "M08878";
            clnAmountPrice.DisplayFormat.FormatString = Resources.NumberFormat;
            clnCoverPlan.DisplayFormat.FormatString = Resources.NumberFormat;
            clnPayableAmount.DisplayFormat.FormatString = Resources.NumberFormat;
            clnUnitPrice.DisplayFormat.FormatString = Resources.NumberFormat;
            //gridColumn5.DisplayFormat.FormatString = Resources.NumberFormat;
            //gridColumn6.DisplayFormat.FormatString = Resources.NumberFormat;
            customGridLookUpEdit1.Properties.DisplayMember = "DrugIdSource.DrugName";
            customGridLookUpEdit1.Properties.DataSource = all;
            customGridLookUpEdit1.Enter += customGridLookUpEdit1_Enter;
            //customGridLookUpEdit1.KeyPress += customGridLookUpEdit1_KeyPress;
            listDetails = new TList<PrescriptionDetail>();
            gridControl1.DataSource = listDetails;
            tb_PatientCode.Focus();
            autoStock = false;
        }

        private void customGridLookUpEdit1_Enter(object sender, EventArgs e)
        {
            customGridLookUpEdit1.SelectAll();
        }


        /// <summary>
        /// </summary>
        /// <param name="sender"> </param>
        /// <param name="e"> </param>
        public void btn_Search_Click(object sender, EventArgs e)
        {
            int Count;
            VList<CmsPatient> cmsPatients =
                DataRepository.CmsPatientProvider.GetPaged("PatientCode='" + tb_PatientCode.Text.Trim() + "'", "", 0,
                                                           Int32.MaxValue, out Count);
            if (Count > 0)
            {
                patient = cmsPatients[0];
                FillPatientInfo();
            }
            else
            {
                MessageBox.Show(Resources.Search_Patient_Result);
            }
        }

        private void FillPatientInfo()
        {
            lbl_PatientCode.Text = patient.PatientCode;
            lbl_PatientName.Text = patient.FullName;
            lbl_Address.Text = String.IsNullOrEmpty(patient.JobAddress) ? " " : patient.JobAddress;
            lbl_DateOfBirth.Text = patient.DateOfBirth != null ? patient.DateOfBirth.Value.ToString("yyyy") : " ";
            customGridLookUpEdit1.Focus();
            Text = patient.FullName;
            RefreshDrugGrid();
        }


        private void tb_PatientCode_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                btn_Search_Click(sender, e);
        }

        private void customGridLookUpEdit1_Closed(object sender, ClosedEventArgs e)
        {
            if (customGridLookUpEdit1.EditValue != null)
            {
                se_Quantity.Focus();
            }
        }


        private void CalculateTotal()
        {
            decimal subTotal = listDetails.Sum(detail => detail.AmountPrice);
            decimal coveredTotal = listDetails.Sum(detail => detail.CoveredPlan);
            decimal payableAmount = subTotal - coveredTotal;
            decimal vat = payableAmount * ServiceFacade.SettingsHelper.VATPercent / 100;
            decimal total = payableAmount + vat;
            string format = Resources.NumberFormat;
            lbl_SubTotal.Text = subTotal.ToString(format);
            lbl_CoveredTotal.Text = coveredTotal.ToString(format);
            lbl_PayableAmount.Text = payableAmount.ToString(format);
            lbl_VAT.Text = vat.ToString(format);
            lbl_Total.Text = total.ToString(format);
        }


        private void btn_DrugAdd_Click(object sender, EventArgs e)
        {
            if (patient == null)
            {
                MessageBox.Show("Please input Patient");
                tb_PatientCode.Focus();
                return;
            }
            if (btn_DrugAdd.Text == "Update")
            {
                if (!customGridLookUpEdit1.EditValue.Equals(DBNull.Value))
                {
                    var objStock = (Stock)customGridLookUpEdit1.EditValue;
                    editItem.DrugId = objStock.DrugId;
                    editItem.Unit = objStock.DrugIdSource.Unit;
                    editItem.DrugName = objStock.DrugIdSource.DrugName;
                    //Over Quantity
                    int quantity = Int32.Parse(se_Quantity.Value.ToString("0"));
                    editItem.Quantity = quantity;
                    editItem.UnitPrice = objStock.DrugIdSource.SellPrice;
                    editItem.CoveredPlan = CalculateCoverPlan(patient.MemberType, editItem.DrugId, editItem.UnitPrice, quantity);
                    btn_DrugAdd.Text = "Add";
                    btn_Clear.Text = "Clear";
                    customGridLookUpEdit1.EditValue = DBNull.Value;
                    se_Quantity.Value = 1;
                    CalculateTotal();
                    gridControl1.RefreshDataSource();
                }
            }
            else
            {
                if (!customGridLookUpEdit1.EditValue.Equals(DBNull.Value))
                {
                    var objStock = (Stock)customGridLookUpEdit1.EditValue;
                    var pDetails = new PrescriptionDetail();
                    pDetails.DrugId = objStock.DrugId;
                    PrescriptionDetail oldItems = listDetails.Find("DrugId", objStock.DrugId);
                    if (oldItems != null)
                    {
                        if (oldItems.Quantity + Int32.Parse(se_Quantity.Value.ToString("0")) > objStock.Quantity)
                            autoStock = true;
                        oldItems.Quantity += Int32.Parse(se_Quantity.Value.ToString("0"));
                        oldItems.CoveredPlan = CalculateCoverPlan(patient.MemberType, oldItems.DrugId, oldItems.UnitPrice, oldItems.Quantity);
                        customGridLookUpEdit1.EditValue = DBNull.Value;
                        se_Quantity.Value = 1;
                        CalculateTotal();
                    }
                    else
                    {
                        if (Int32.Parse(se_Quantity.Value.ToString("0")) > objStock.Quantity)
                            autoStock = true;
                        pDetails.Unit = objStock.DrugIdSource.Unit;
                        pDetails.DrugName = objStock.DrugIdSource.DrugName;
                        pDetails.Quantity = Int32.Parse(se_Quantity.Value.ToString("0"));
                        pDetails.UnitPrice = objStock.DrugIdSource.SellPrice;
                        pDetails.CoveredPlan = CalculateCoverPlan(patient.MemberType, pDetails.DrugId, pDetails.UnitPrice, pDetails.Quantity);
                        listDetails.Add(pDetails);
                        customGridLookUpEdit1.EditValue = DBNull.Value;
                        se_Quantity.Value = 1;
                        CalculateTotal();
                    }
                    gridControl1.RefreshDataSource();
                }
            }
            customGridLookUpEdit1.Focus();
        }

        private static decimal CalculateCoverPlan(string memberType, string drugId, decimal unitPrice, int quantity)
        {
            DrugDiscount discount = DataRepository.DrugDiscountProvider.GetByMemberTypeDrugId(memberType, drugId);
            if (discount != null)
                return (unitPrice * discount.DiscountPercent / 100) * quantity;
            return 0;
        }

        private void RefreshDrugGrid()
        {
            foreach (var detail in listDetails)
            {
                detail.CoveredPlan = CalculateCoverPlan(patient.MemberType, detail.DrugId, detail.UnitPrice, detail.Quantity);
            }
            gridControl1.RefreshDataSource();
            CalculateTotal();
        }

        private void btnEdit_ButtonClick(object sender, ButtonPressedEventArgs e)
        {
            editItem = (PrescriptionDetail)gridView1.GetRow(gridView1.FocusedRowHandle);
            Stock stock = all.Find("DrugId", editItem.DrugId);
            se_Quantity.Value = editItem.Quantity;
            btn_DrugAdd.Text = "Update";
            btn_Clear.Text = "Cancel";
            customGridLookUpEdit1.EditValue = stock;
            //customGridLookUpEdit1.Focus();
        }

        private void btnDelete_ButtonClick(object sender, ButtonPressedEventArgs e)
        {
            if (btn_DrugAdd.Text == "Update")
                customGridLookUpEdit1.Focus();
            else
            {
                var deleteItem = (PrescriptionDetail)gridView1.GetRow(gridView1.FocusedRowHandle);
                listDetails.Remove(deleteItem);
                CalculateTotal();
            }
        }


        //For Auto Balance Stock By Create PO, GRN 
        private bool AutoStock()
        {
            if (autoStock)
            {
                string grnId = "A" + ServiceFacade.SettingsHelper.GRNPrefix + DateTime.Now.ToString("yyMMdd") +
                               "001";
                string poid = "A" + ServiceFacade.SettingsHelper.POPrefix + DateTime.Now.ToString("yyMMdd") + "001";
                TransactionManager objTransactionManager = DataRepository.Provider.CreateTransaction();
                objTransactionManager.BeginTransaction();
                try
                {
                    Po po = DataRepository.PoProvider.GetByPoId(objTransactionManager, poid);
                    if (po == null)
                    {
                        po = new Po();
                        po.PoId = poid;
                        po.PoDate = DateTime.Now;
                        po.RequestBy = Program.GlobalUser.UserId;
                        po.IsComplete = true;
                        DataRepository.PoProvider.Insert(objTransactionManager, po);
                    }
                    //Create or Update GRN
                    Grn grn = DataRepository.GrnProvider.GetByGrnId(objTransactionManager, grnId);
                    if (grn == null)
                    {
                        grn = new Grn();
                        grn.PoId = poid;
                        grn.GrnId = grnId;
                        grn.SupplierId = "S001";
                        grn.GrnDate = DateTime.Now;
                        grn.PreparedBy = Program.GlobalUser.UserId;
                        grn.IsComplete = true;
                        DataRepository.GrnProvider.Insert(objTransactionManager, grn);
                    }
                    foreach (PrescriptionDetail detail in listDetails)
                    {
                        //Create or Update PO

                        string whereExpression = string.Format("PoId='{0}' And DrugId='{1}'", poid,
                                                               detail.DrugId);
                        int count = 0;
                        PoDetails objDetails;
                        TList<PoDetails> list = DataRepository.PoDetailsProvider.GetPaged(objTransactionManager,
                                                                                          whereExpression, "", 0, 1,
                                                                                          out count);
                        if (count > 0)
                            objDetails = list[0];
                        else
                            objDetails = new PoDetails();
                        TList<Stock> max = DataRepository.StockProvider.GetMax(objTransactionManager, detail.DrugId);
                        int poQuantity = detail.Quantity;
                        int maxStock = 0;
                        if (max.Count > 0)
                            maxStock = max[0].Quantity;
                        if (poQuantity > maxStock)
                        {
                            poQuantity = poQuantity - maxStock;
                            objDetails.Quantity += poQuantity;
                            objDetails.RemainQuantity = 0;
                            objDetails.PoId = poid;
                            objDetails.DrugId = detail.DrugId;
                            objDetails.Remark = "Auto PO";
                            DataRepository.PoDetailsProvider.Save(objTransactionManager, objDetails);

                            whereExpression = string.Format("GrnId='{0}' And DrugId='{1}'", grnId,
                                                            detail.DrugId);
                            GrnDetails grnDetails;
                            TList<GrnDetails> grnDetailslist =
                                DataRepository.GrnDetailsProvider.GetPaged(objTransactionManager, whereExpression,
                                                                           "", 0,
                                                                           1, out count);
                            if (count > 0)
                                grnDetails = grnDetailslist[0];
                            else
                                grnDetails = new GrnDetails();
                            grnDetails.Quantity += poQuantity;
                            grnDetails.DrugId = detail.DrugId;
                            grnDetails.GrnId = grnId;
                            grnDetails.PoQuantity += poQuantity;
                            grnDetails.Remark = "Auto GRN";
                            DataRepository.GrnDetailsProvider.Save(objTransactionManager, grnDetails);
                            //Create or Update Stock
                            Stock newStock =
                                DataRepository.StockProvider.GetByDrugIdExpDateBatchLot(objTransactionManager,
                                                                                        detail.DrugId, null,
                                                                                        null);
                            if (newStock == null)
                            {
                                newStock = new Stock();
                                newStock.DrugId = detail.DrugId;
                            }
                            newStock.Quantity += poQuantity;
                            DataRepository.StockProvider.Save(objTransactionManager, newStock);
                        }
                    }
                }
                catch (Exception ex)
                {
                    objTransactionManager.Rollback();
                    MessageBox.Show("Error " + ex.Message);
                    return false;
                }
                objTransactionManager.Commit();
            }
            return true;
        }

        private void btn_Print_Click(object sender, EventArgs e)
        {
            if (patient != null)
            {
                string prescriptionId;
                var Perfix = ServiceFacade.SettingsHelper.PrescriptionPrefix + DateTime.Now.ToString("yyMMdd");
                var Count = 0;
                var objPrescriptions =
                    DataRepository.PrescriptionProvider.GetPaged("PrescriptionId like '" + Perfix + "' + '%'",
                                                                 "PrescriptionId desc", 0, 1, out Count);
                CalculateTotal();
                if (Count == 0)
                    prescriptionId = Perfix + "001";
                else
                    prescriptionId = Perfix +
                                     String.Format("{0:000}",
                                                   int.Parse(
                                                       objPrescriptions[0].PrescriptionId.Substring(
                                                           objPrescriptions[0].PrescriptionId.Length - 3)) + 1);
                var insertP = new Prescription
                                  {
                                      PrescriptionId = prescriptionId,
                                      DeliveryDate = DateTime.Now,
                                      DateOfBirth = patient.DateOfBirth,
                                      CreateDate = DateTime.Now,
                                      Address = lbl_Address.Text,
                                      PatientCode = lbl_PatientCode.Text,
                                      PatientName = lbl_PatientName.Text,
                                      SalesPerson = Program.GlobalUser.UserId,
                                      TotalAmount = Decimal.Parse(lbl_Total.Text),
                                      CoveredTotal = Decimal.Parse(lbl_CoveredTotal.Text),
                                      PayableAmount = Decimal.Parse(lbl_PayableAmount.Text),
                                      Vat = Decimal.Parse(lbl_VAT.Text),
                                      Amount = Decimal.Parse(lbl_SubTotal.Text)
                                  };
                if (AutoStock())
                    if (StockOut(insertP))
                    {
                        insertP.PrescriptionDetailCollection = listDetails;
                        PrintDeliveryNote(insertP);
                        var formPrescriptionLabel = new FormPrescriptionLabel();
                        formPrescriptionLabel.LoadDefault(insertP.PrescriptionId);
                        formPrescriptionLabel.Show();
                        LoadDefault();
                        FillBlankPatient();
                        patient = null;
                    }
            }
            else
            {
                MessageBox.Show("Please input Patient");
                tb_PatientCode.Focus();
            }
        }

        // Stock Out
        public bool StockOut(Prescription insertP)
        {
            TransactionManager transaction = DataRepository.Provider.CreateTransaction();
            transaction.BeginTransaction();
            try
            {
                DataRepository.PrescriptionProvider.Insert(transaction, insertP);
                foreach (PrescriptionDetail detail in listDetails)
                {
                    detail.PrescriptionId = insertP.PrescriptionId;
                    TList<Stock> items = DataRepository.StockProvider.GetItems(transaction, detail.DrugId);
                    DrugDispo drug = DataRepository.DrugDispoProvider.GetByDrugId(detail.DrugId);
                    int quantity = detail.Quantity;
                    int oldQuantity = detail.Quantity;
                    int Count = 0;
                    while (quantity > 0)
                    {
                        detail.ExpDate = items[Count].ExpDate;
                        detail.BatchLot = items[Count].BatchLot;
                        detail.IsControlDrug = drug.IsControlDrug;
                        if (items[Count].Quantity > quantity)
                        {
                            items[Count].Quantity -= quantity;
                            detail.Quantity = quantity;
                            detail.CoveredPlan = CalculateCoverPlan(patient.MemberType, detail.DrugId, detail.UnitPrice,
                                                                    detail.Quantity);
                            DataRepository.PrescriptionDetailProvider.Insert(transaction, detail);
                            DataRepository.StockProvider.Update(transaction, items[Count]);
                            quantity = 0;
                        }
                        else
                        {
                            quantity -= items[Count].Quantity;
                            detail.Quantity = items[Count].Quantity;
                            detail.CoveredPlan = CalculateCoverPlan(patient.MemberType, detail.DrugId, detail.UnitPrice,
                                                                    detail.Quantity);
                            DataRepository.PrescriptionDetailProvider.Insert(transaction, detail);
                            DataRepository.StockProvider.Delete(transaction, items[Count++]);
                        }
                    }
                    detail.Quantity = oldQuantity;
                }
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                MessageBox.Show("Error " + ex.Message);
                return false;
            }
            transaction.Commit();
            return true;
        }


        private void PrintDeliveryNote(Prescription printP)
        {
            Utilities.CreateDBF(printP);
            bool canPrint = true;
            bool printControlDrug = Utilities.PreviewDeliveryNote(printP, reportViewer1,
                                                                  ServiceFacade.SettingsHelper.DnCustomerCopy, false, "",
                                                                  ref canPrint);
            if (canPrint)
            {
                var printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
                printDoc.Print();
                Utilities.PreviewDeliveryNote(printP, reportViewer1, ServiceFacade.SettingsHelper.DnFileCopy, false, "",
                                              ref canPrint);
                printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
                printDoc.Print();
                Utilities.PreviewDeliveryNote(printP, reportViewer1, ServiceFacade.SettingsHelper.DnAccountantCopy, false, "",
                                              ref canPrint);
                printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
                printDoc.Print();
                //Utilities.PreviewDeliveryNote(printP, reportViewer1, ServiceFacade.SettingsHelper.DnPharmacyCopy, false,
                //                              "", ref canPrint);
                //printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
                //printDoc.Print();
                //Utilities.PreviewDeliveryNote(printP, reportViewer1, ServiceFacade.SettingsHelper.DnAccountantCopy,
                //                              false, "", ref canPrint);
                //printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
                //printDoc.Print();
            }
            //Utilities.PreviewDeliveryNote(printP, reportViewer1, ServiceFacade.SettingsHelper.DnFileCopy, false, "");
            //printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
            //printDoc.Print();
            //Utilities.PreviewDeliveryNote(printP, reportViewer1, ServiceFacade.SettingsHelper.DnPharmacyCopy, false, "");
            //printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
            //printDoc.Print();
            //Utilities.PreviewDeliveryNote(printP, reportViewer1, ServiceFacade.SettingsHelper.DnAccountantCopy, false,
            //                              "");
            //printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
            //printDoc.Print();
            if (printControlDrug)
                PrintControlDrug(printP);
        }

        private void PrintControlDrug(Prescription printP)
        {
            Utilities.PreviewControlDrug(printP, reportViewer1, ServiceFacade.SettingsHelper.DnCustomerCopy, false, "");
            var printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
            printDoc.Print();
            Utilities.PreviewControlDrug(printP, reportViewer1, ServiceFacade.SettingsHelper.DnFileCopy, false, "");
            printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
            printDoc.Print();
            //Utilities.PreviewControlDrug(printP, reportViewer1, ServiceFacade.SettingsHelper.DnPharmacyCopy, false, "");
            //printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
            //printDoc.Print();
            //Utilities.PreviewControlDrug(printP, reportViewer1, ServiceFacade.SettingsHelper.DnAccountantCopy, false, "");
            //printDoc = new ReportPrintDocument(reportViewer1.LocalReport);
            //printDoc.Print();
        }

        //private void btn_PatientAdd_Click(object sender, EventArgs e)
        //{
        //    var patientAdd = new PatientAdd();
        //    patientAdd.PrescriptionForm = this;
        //    patientAdd.ShowDialog();
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="patientCode"></param>
        /// <param name="patientName"></param>
        /// <param name="dateOfBirth"></param>
        /// <param name="address"></param>
        public void FillBlankPatient()
        {
            tb_PatientCode.Text = "";
            lbl_PatientCode.Text = " ";
            lbl_PatientName.Text = " ";
            lbl_Address.Text = " ";
            lbl_DateOfBirth.Text = " ";
            CalculateTotal();
            //patient = new CmsPatient
            //              {
            //                  PatientCode = patientCode,
            //                  FullName = patientName,
            //                  JobAddress = address,
            //                  DateOfBirth = dateOfBirth
            //              };
            //FillPatientInfo();
        }

        private void btn_Reset_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("This will clear all information in form", "Reset Form", MessageBoxButtons.OKCancel) ==
                DialogResult.OK)
            {
                LoadDefault();
                CalculateTotal();
                FillBlankPatient();
                tb_PatientCode.Text = "";
            }
        }

        private void gridView1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
                btnDelete_ButtonClick(sender, null);
            else if (e.KeyCode == Keys.F2)
            {
                btnEdit_ButtonClick(sender, null);
                customGridLookUpEdit1.Focus();
            }
        }

        private void btn_Clear_Click(object sender, EventArgs e)
        {
            btn_Clear.Text = "Clear";
            btn_DrugAdd.Text = "Add";
            customGridLookUpEdit1.EditValue = DBNull.Value;
            se_Quantity.Value = 1;
            customGridLookUpEdit1.Focus();
        }

        private void customGridLookUpEdit1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (char.IsLetterOrDigit(e.KeyChar) && (!customGridLookUpEdit1.IsPopupOpen))
            {
                customGridLookUpEdit1.ShowPopup();
                SendKeys.Send(e.KeyChar.ToString());
                e.Handled = true;
            }
        }
    }
}